In GNU C++, you can use the keyword signature to define a completely abstract class interface as a datatype. You can connect this abstraction with actual classes using signature pointers. If you want to use signatures, run the GNU compiler with the -fhandle-signatures command-line option. (With this option, the compiler reserves a second keyword sigof as well, for a future extension.)
Roughly, signatures are type abstractions or interfaces of classes, and are similar to Objective-C's protocols. Some other languages have similar facilities. C++ signatures are related to ML's signatures, Haskell's type classes, definition modules in Modula-2, interface modules in Modula-3, abstract types in Emerald, type modules in Trellis/Owl, categories in Scratchpad II, and types in POOL-I. For a more detailed discussion of signatures, see Signatures: A Language Extension for Improving Type Abstraction and Subtype Polymorphism in C++ by Gerald Baumgartner and Vincent F. Russo (Tech report CSD-TR-95-051, Dept. of Computer Sciences, Purdue University, August 1995, a slightly improved version appeared in Software--Practice & Experience , 25(8), pp. 863-889, August 1995). You can get the tech report by anonymous FTP from ftp.cs.purdue.edu in pub/gb/Signature-design.ps.gz .
Syntactically, a signature declaration is a collection of member function declarations and nested type declarations. For example, this signature declaration defines a new abstract type S with member functions int foo () and int bar (int) :
signature S {
int foo ();
int bar (int);
};
Since signature types do not include implementation definitions, you cannot write an instance of a signature directly. Instead, you can define a pointer to any class that contains the required interfaces as a "signature pointer". Such a class "implements" the signature type.
To use a class as an implementation of S , you must ensure that the class has public member functions int foo () and int bar (int) . The class can have other member functions as well, public or not; as long as it offers what's declared in the signature, it is suitable as an implementation of that signature type.
For example, suppose that C is a class that meets the requirements of signature S ( C "conforms to" S ). Then
C obj;
S * p = &obj;
defines a signature pointer p and initializes it to point to an object of type C . The member function call int i = p->foo (); executes obj.foo () .
Abstract virtual classes provide somewhat similar facilities in standard C++. There are two main advantages to using signatures instead:
There is one more detail about signatures. A signature declaration can contain member function definitions as well as member function declarations. A signature member function with a full definition is called a default implementation ; classes need not contain that particular interface in order to conform. For example, a class C can conform to the signature
signature T {
int f (int);
int f0 () {
return f (0);
};
};
whether or not C implements the member function int f0 () . If you define C::f0 , that definition takes precedence; otherwise, the default implementation S::f0 applies.